package pactera.tf.controller;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.alibaba.fastjson.JSONObject;

import pactera.tf.dataobj.ChatMsgDO;
import pactera.tf.dataobj.GroupChatMsgDO;
import pactera.tf.mq.ChatMsgProducer;
import pactera.tf.service.ChatMsgService;
import pactera.tf.service.GroupChatMsgService;
import pactera.tf.service.GroupChatService;

/**
 * @ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * @ServerEndpoint 可以把当前类变成websocket服务类
 */
@Controller
@ServerEndpoint(value = "/websocket/{userno}")
public class ChatWebSocketController {
    /**
     * concurrent包的线程安全map，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
     */
    private static ConcurrentHashMap<String, ChatWebSocketController> webSocketSet = new ConcurrentHashMap<String, ChatWebSocketController>();
    /**
     * 	与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session webSocketsession;
    /**
     * 	当前发消息的人员编号
     */
    private String userno = "";
    
    private static ChatMsgService chatMsgService;
    @Autowired
	public  void setChatMsgService(ChatMsgService chatMsgService) {
		ChatWebSocketController.chatMsgService = chatMsgService;
	}
    private static GroupChatMsgService groupChatMsgService;
    @Autowired
	public  void setGroupChatMsgService(GroupChatMsgService groupChatMsgService) {
		ChatWebSocketController.groupChatMsgService = groupChatMsgService;
	}
    /**
     * 	消息队列生产者
     */
    private static ChatMsgProducer chatMsgProducer;
    @Autowired
    public void setChatMsgProducer(ChatMsgProducer chatMsgProducer) {
        ChatWebSocketController.chatMsgProducer = chatMsgProducer;
    }
    private  GroupChatService groupChatService ;
    @Autowired
	public void setGroupChatService(GroupChatService groupChatService) {
		this.groupChatService = groupChatService;
	}


	/**
     * 
    
     * <p>Title: onOpen</p>  
    
     * <p>Description:连接建立成功调用的方法。session为与某个客户端的连接会话，需要通过它来给客户端发送数据 </p>  
    
     * @param param
     * @param webSocketsession
     */
    @OnOpen
    public void onOpen(@PathParam(value = "userno") String param, Session webSocketsession) {
        /**
         * 接收到发送消息的人员编号
         */
        userno = param;
        this.webSocketsession = webSocketsession;

        /**
         * 加入map中
         */
        webSocketSet.put(param, this);
    }


    /**
     * 
    
     * <p>Title: onClose</p>  
    
     * <p>Description:连接关闭调用的方法 </p>
     */
    @OnClose
    public void onClose() {
        if (!"".equals(userno)) {
            webSocketSet.remove(userno);
        }
    }


    
    /**
     * 
    
     * <p>Title: onMessage</p>  
    
     * <p>Description:  收到客户端消息后调用的方法</p>  
    
     * @param chatmsg 客户端发送过来的消息
     * @param session 可选的参数
     */
    @SuppressWarnings("unused")
	@OnMessage
    public void onMessage(String chatmsg, Session session) {
        JSONObject jsonObject = JSONObject.parseObject(chatmsg);
        if (jsonObject.containsKey("groupId")) {
        	chatMsgProducer.sendForGroup(chatmsg);
        }else if(jsonObject.containsKey("reciveuserid") && "sys".equals(jsonObject.getString("reciveuserid"))) {
        	sendAll(jsonObject.getString("reciveuserid"),chatmsg);
        }else {
            chatMsgProducer.sendForPointToPoint(chatmsg);
        }
    }


   
    /**
     * 
    
     * <p>Title: sendToUser</p>  
    
     * <p>Description:  给指定的人发送消息</p>  
    
     * @param chatMsg 消息对象
     */
    public void sendToUser(ChatMsgDO chatMsg) {
    	String sendUserId = chatMsg.getSendUserId();
        String reviceUserId = chatMsg.getReciveUserId();
        String sendMessage = chatMsg.getSendText();
        String msgType = chatMsg.getMsgType();
        chatMsgService.insertChatMsg(new ChatMsgDO().setMsgType(chatMsg.getMsgType()).setReciveUserId(reviceUserId).setSendUserId(sendUserId).setSendText(sendMessage));
	        try {
	            if (webSocketSet.get(reviceUserId) != null) {
	                webSocketSet.get(reviceUserId).sendMessage(sendUserId+"|"+sendMessage+"|"+msgType);
	            }else{
	                webSocketSet.get(sendUserId).sendMessage("0"+"|"+"当前用户不在线");
	            }
	        } catch (IOException e) {
	            e.printStackTrace();
	        }
    }

    
    /**
     * 
    
     * <p>Title: sendToAll</p>  
    
     * <p>Description:给所有人发送消息 </p>  
    
     * @param groupChatMsgDO
     */
    public void sendToAll(GroupChatMsgDO groupChatMsgDO) {
        String sendMessage = groupChatMsgDO.getSendText();
        String sendId = groupChatMsgDO.getSendUserId();
        String groupId = groupChatMsgDO.getGroupId();
        String msgType = groupChatMsgDO.getMsgType();
        groupChatMsgService.insertChatMsg(groupChatMsgDO);
        for (String key : webSocketSet.keySet()) {
        	// 判断哪些用户在群里面
        	List<String> users = groupChatService.getUserByGroupId(groupId);
        	if(users != null) {
	        		 try {
	                     // 判断接收用户是否是当前发消息的用户
	                     if (!sendId.equals(key) && users.contains(key)) {
	                         webSocketSet.get(key).sendMessage(groupId+"|"+sendMessage+"|"+msgType+"|"+sendId);
	                         System.out.println("key = " + key);
	                     }
	                 } catch (IOException e) {
	                     e.printStackTrace();
	                 }
        	}
           
        }
    }


    
    /**
     * 
    
     * <p>Title: onError</p>  
    
     * <p>Description:发生错误时的回调函数 </p>  
    
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }


   
    /**
     * 
    
     * <p>Title: sendMessage</p>  
    
     * <p>Description: 发送信息给前端</p>  
    
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
    	synchronized (this.webSocketsession) {
    		this.webSocketsession.getBasicRemote().sendText(message);
    	}
    }

    
    /**
     * 给所有人发消息
     *
     * @param message
     */
    public void sendAll(String userid,String message) {
        JSONObject jsonobj= JSONObject.parseObject(message);
    	String sendMessage = jsonobj.getString("sendtext");
        //遍历HashMap
        for (String key : webSocketSet.keySet()) {
            try {
                //判断接收用户是否是当前发消息的用户
                if (userno.equals(key)) {
                    webSocketSet.get(key).sendMessage(userid+"|"+sendMessage);
                    System.out.println("key = " + key);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
}

